package cn.tedu.charging.order.quartz;

import cn.tedu.charging.order.dao.mapper.OrderFailMapper;
import cn.tedu.charging.order.dao.mapper.OrderSuccessMapper;
import cn.tedu.charging.order.dao.repository.OrderRepository;
import cn.tedu.charging.order.dao.repository.impl.OrderRepositoryImpl;
import cn.tedu.charging.order.pojo.po.ChargingOrderFailPO;
import cn.tedu.charging.order.pojo.po.ChargingOrderSuccessPO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.util.Date;

/**
 * 检查任务
 * 用来 检查 设备无响应
 *
 * DeviceCheckJob 不能在 Spring容器中，在订单服务启动的时候创建任务了
 * 每个订单一个任务 应该在创建订单的时候 创建任务
 */

@Slf4j
public class DeviceCheckJob implements Job {


    /**
     * 必须有一个无参数的构造器
     *  如果没有， 在初始化 new DeviceCheckJob 调用 Class newInstance 实例化，
     *  通过无参的构造器实例化对象
     *  getConstructor0() 获取无参构造器
     *  public DeviceCheckJob(String orderNo) 覆盖 默认的无参构造器
     *  找不到方法 抛异常 NoSuchMethodException  找不到构造器，创建不了 DeviceCheckJob对象
     */


    public DeviceCheckJob() {

    }


    public DeviceCheckJob(String orderNo) throws SchedulerException {


        log.debug("创建定时任务");

        //创建调度器工厂
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        //获取调度器
        Scheduler scheduler = schedulerFactory.getScheduler();

        //获取当前时间
        long now = System.currentTimeMillis();
        //获取当前时间的一分钟之后
        long deviceCheckTime = now + 60 * 1000;
        //把时间戳转换为Java.util.Date对象
        Date triggerTime = new Date(deviceCheckTime);

        //定义触发器
        Trigger trigger =
                TriggerBuilder.newTrigger().startAt(triggerTime).build();

         //任务详情
        JobDetail jobDetail =
                JobBuilder.newJob(DeviceCheckJob.class)
                        .withIdentity("deviceCheckJob" + orderNo, "deviceCheckJobGroup")
                        .usingJobData("orderNo", orderNo)
                        .build();

        //调度器 把任务和触发器进行绑定
        //调度器 scheduler,让任务 JobDetail 和 按照 触发器的 时间 来触发
        scheduler.scheduleJob(jobDetail, trigger);
        //启动调度器
        scheduler.start();


    }
    /**
     * 任务执行的逻辑 具体的任务
     *
     * 任务执行的逻辑 具体的任务
     * 7. 判断是否有订单记录
     * 8. 有成功订单记录 订单状态是 充电中 说明设备 有响应，设备收到了指令后，正常的返回开始充电成功的响应，保存成功订单记录  无需处理
     * 9. 没有成功订单记录
     * 10. 判断是否有失败订单记录
     * 11. 有失败订单记录   失败原因 有响应-无法充电  无需处理
     * 12. 没有失败订单记录
     * 13. 插入失败订单记录 失败原因 设备无响应 通知用户和维修人员 设置枪状态为 故障
     * @param context
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.debug("任务开始执行");
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String orderNo = jobDataMap.getString("orderNo");
        log.debug("任务开始执行,获取订单号订单号:{}", orderNo);

        OrderRepository orderRepository = SpringContextUtils.getBean(OrderRepository.class);

        log.debug("查询成功订单记录:订单号{}", orderNo);

        //7. 判断是否有订单记录
//        QueryWrapper queryWrapper = new QueryWrapper();
//        queryWrapper.eq("bill_id", orderNo);
//        ChargingOrderSuccessPO chargingOrderSuccessPO =
//                orderSuccessMapper.selectOne(queryWrapper);
        ChargingOrderSuccessPO chargingOrderSuccessPO = orderRepository.getOrderSuccessByOrderNo(orderNo);
        log.debug("查询成功订单记录:订单号{},查询结果{}", orderNo, chargingOrderSuccessPO);

        //8. 判断是否有有成功订单记录

        if (chargingOrderSuccessPO == null){
            //没有成功订单记录
            log.debug("没有成功订单记录,查询是否有失败订单记录");
            log.debug("查询失败订单记录:订单号{}", orderNo);

//            OrderFailMapper orderFailMapper = SpringContextUtils.getBean(OrderFailMapper.class);
//            QueryWrapper failqueryWrapper = new QueryWrapper();
//            failqueryWrapper.eq("bill_id", orderNo);
//            ChargingOrderFailPO chargingOrderFailPO = orderFailMapper.selectOne(failqueryWrapper);
            ChargingOrderFailPO chargingOrderFailPO = orderRepository.getOrderFailByOrderNo(orderNo);
            //9. 判断是否有失败订单记录
            if (chargingOrderFailPO == null) {
                log.debug("没有失败订单记录,插入失败订单记录");
                ChargingOrderFailPO failPO = new ChargingOrderFailPO();
                failPO.setBillId(orderNo);
                failPO.setFailDesc("设备故障-无响应");
                log.debug("插入失败订单记录:{}", failPO);
                int row = orderRepository.insertOrderFail(failPO);
                log.debug("插入失败订单记录:{},影响行数:{}", failPO, row);

                log.debug("设备发送的消息是 开始充电失败 <<通知用户>>,提醒用户更换设备");
                log.debug("给用户发送优惠券，表示歉意，给用户心灵上的安慰");
                log.debug("修改枪的状态为 <<故障>>");
                log.debug("<<通知设备管理员>> 进行设备的检修");
            } else {
                log.debug("有失败订单记录,失败原因有<设备有响应-无法充电>，无需处理");
            }
        }else {
            log.debug("有成功订单记录,订单状态是 充电中 说明设备 有响应");
        }



    }
}
